#include <stdio.h>
#include <string.h>
#include <mysql/mysql.h>
#include <stdlib.h>  // atoi
#include <stdbool.h>

MYSQL *db = NULL;  // 数据库对象 
MYSQL_STMT *stmt = NULL; // 语句处理器

void show_err(void){
    printf("error: %s\n", mysql_error(db));
}

void show_err2(void){
    printf("stmt error: %s\n", mysql_stmt_error(stmt));
}

int connect_db(char *user, char *pwd){
    mysql_library_init(0, NULL, NULL);
    db = mysql_init(NULL);
    if(db == NULL){
        printf("--init fail--\n");
        return -1;
    }

    if(mysql_real_connect(db, "localhost", user, pwd, "cloudfs", 3306, NULL, 0) == NULL){
        show_err();
        return -1;
    }

    return 0;
}

void close_db(){
    if(stmt != NULL)
        mysql_stmt_close(stmt);

    if(db != NULL)
        mysql_close(db);
    mysql_library_end();
}

int query_stmt(char *sql, MYSQL_BIND *binds){
    if(stmt == NULL)
        stmt = mysql_stmt_init(db);
    if(mysql_stmt_prepare(stmt,sql, strlen(sql)) != 0)
    {
        show_err2();
        return -1;
    }

    if(mysql_stmt_bind_param(stmt, binds) != 0){
        show_err2();
        return -1;
    }

    if(mysql_stmt_execute(stmt) != 0){
        show_err2();
        return -1;
    }

    // 获取结果集中的元数据
    MYSQL_RES *res1 = mysql_stmt_result_metadata(stmt);
    if(res1 == NULL) {
        printf("无结果集\n");
        mysql_stmt_free_result(stmt);
        return 0;
    }
    int cols = mysql_num_fields(res1);

    MYSQL_BIND *results = malloc(cols * sizeof(MYSQL_BIND));
    my_bool *is_null = malloc(cols * sizeof(my_bool));  // 是否为NULL
    unsigned long *lengths = malloc(cols * sizeof(unsigned long)); // 记录实际数据长度
    memset(results, 0, cols * sizeof(MYSQL_BIND));
    memset(is_null, 0, cols * sizeof(my_bool));
    memset(lengths, 0, cols * sizeof(unsigned long));

    for(int i=0; i<cols; i++){ 
        MYSQL_FIELD *field = mysql_fetch_field_direct(res1, i);
        printf("---%s, type(%d), len(%ld)---\n", field->name, field->type, field->length);
        results[i].buffer_type = field->type;
        results[i].is_null = &is_null[i];
        results[i].length = &lengths[i];  // 记录实际数据长度
        
        // 根据不同类型分配内存
        if(field->type == MYSQL_TYPE_LONG){
            results[i].buffer = malloc(sizeof(int));
            results[i].buffer_length = sizeof(int);
        } else {
            // 分配内存+1用于字符串结束符
            results[i].buffer = malloc(field->length + 1);
            results[i].buffer_length = field->length;
        }
    } 

    // 绑定查询结果的字段
    if(mysql_stmt_bind_result(stmt, results) != 0){
        show_err2();
        // 清理资源
        for(int i=0; i<cols; i++) free(results[i].buffer);
        free(results);
        free(is_null);
        free(lengths);
        mysql_free_result(res1);
        return -1;
    }

    // 获取查询结果（一次性的）
    if(mysql_stmt_store_result(stmt) != 0){
        show_err2();
        // 清理资源
        for(int i=0; i<cols; i++) free(results[i].buffer);
        free(results);
        free(is_null);
        free(lengths);
        mysql_free_result(res1);
        return -1; 
    } else {
        printf("获取结果集OK, %lld行\n", (long long)mysql_stmt_num_rows(stmt));
        while(mysql_stmt_fetch(stmt) == 0){
            printf("----数据行---\n");
            for(int i=0; i<cols; i++){
                // 处理NULL值
                if(is_null[i]){
                    printf("%10s\t", "NULL");
                    continue;
                }
                
                // 添加字符串结束符（如果需要）
                if(results[i].buffer_type != MYSQL_TYPE_LONG && results[i].buffer != NULL) {
                    char *buf = (char*)results[i].buffer;
                    if(lengths[i] < results[i].buffer_length)
                        buf[lengths[i]] = '\0';
                    else
                        buf[results[i].buffer_length-1] = '\0';
                }
                
                // 根据不同数据类型打印
                if(results[i].buffer_type == MYSQL_TYPE_LONG){
                    printf("%10d\t", *((int *)results[i].buffer));
                } else {
                    printf("%10s\t", (char *)results[i].buffer);
                }
            }
            printf("\n");
        }
    }

    // 释放资源
    for(int i=0; i<cols; i++) free(results[i].buffer);
    free(results);
    free(is_null);
    free(lengths);
    mysql_free_result(res1);
    mysql_stmt_free_result(stmt);
    mysql_stmt_reset(stmt);

    return 0;
}

// ./q <page> <page_size>
// 分页查询：limit (page-1)*page_size, page_size;
int main(int argc, char const *argv[])
{
    if(argc != 3) {
        printf("用法: %s <page> <page_size>\n", argv[0]);
        return -1;
    }
    if(connect_db("root", "root") != 0){
        return -1;
    }
    
    printf("---数据库连接成功--\n");

    char sql[] = "select * from t_user limit ?,?";
    
    MYSQL_BIND binds[2];
    int page = atoi(argv[1]);
    int page_size = atoi(argv[2]);
    int offset = (page - 1) * page_size;

    // 使用MYSQL_TYPE_LONG绑定整数参数
    memset(binds, 0, sizeof(binds));
    binds[0].buffer_type = MYSQL_TYPE_LONG;
    binds[0].buffer = (void*)&offset;
    binds[0].buffer_length = sizeof(offset);

    binds[1].buffer_type = MYSQL_TYPE_LONG;
    binds[1].buffer = (void*)&page_size;
    binds[1].buffer_length = sizeof(page_size);

    printf("查询: 偏移 %d, 页大小 %d\n", offset, page_size);
    int ret = query_stmt(sql, binds);
    printf("-----执行结果(%d)------\n", ret);

    close_db();
    return 0;
}